#pragma once

#include <vector>
#include "constant.hh"

namespace icehpc
{
    struct point
    {
        double x;
        double y;
    };

    // 维护解的正六边形区域相关的数据以及函数
    struct hexagon
    {
        using size_type = int;
        using value_type = double;

        // 正六边形中心在 (0, 0)
        hexagon(size_type div, value_type length = 2./constant::r3);

        bool       boundary(size_type x, size_type y) const;
        bool         inside(size_type x, size_type y) const;
        bool        outside(size_type x, size_type y) const;
        bool            top(size_type x, size_type y) const;
        bool         bottom(size_type x, size_type y) const;
        point      real_pos(size_type x, size_type y) const;
        size_type  identity(size_type x, size_type y) const;
        value_type    value(size_type x, size_type y) const;

        // 根据一个点的 id 判断这个点在不在边界上
        bool          boundary(size_type id) const;
        // 根据一个点的 id 判断这个点在不在区域内
        bool            inside(size_type id) const;
        // 根据一个点的 id 判断这个点在不在区域外
        bool           outside(size_type id) const;
        // 根据一个点的 id 判断这个点在不在顶边
        bool               top(size_type id) const;
        // 根据一个点的 id 判断这个点在不在底边
        bool            bottom(size_type id) const;
        // 根据一个点的 id 返回实际的坐标
        point         real_pos(size_type id) const;
        // 根据一个点的 id 上面相邻点的 id
        size_type           up(size_type id) const;
        // 根据一个点的 id 下面相邻点的 id
        size_type         down(size_type id) const;
        // 根据一个点的 id 左边相邻点的 id
        size_type         left(size_type id) const;
        // 根据一个点的 id 右边相邻点的 id
        size_type        right(size_type id) const;
        // 返回某个点在 x 方向上相邻不为空的 id，即如果这个点在右边界的话会返回
        // 它左边的 id
        size_type  x_non_empty_dir(size_type id) const;
        // 返回某个点在 y 方向上相邻不为空的 id
        size_type  y_non_empty_dir(size_type id) const;
        // 根据一个点的 id 返回它所在位置的 f 的值
        value_type       value(size_type id) const;

        // x 方向 1/2 边长划分数，详细见报告
        size_type div;
        // 矩形区域的宽，即 x 方向点的个数
        size_type width;
        // 矩形区域的高，即 y 方向点的个数
        size_type height;
        // 矩形区域点的个数
        size_type n;
        // 实际求解的正六边形区域点的个数
        size_type nactive;

        // 为了固定解的固定点 id
        size_type except_id;

        // 正六边形边长
        value_type length;
        // x 方向划分长度，y 方向是其 sqrt(3) 倍
        value_type delta;
        // 题中的常数 c
        value_type c;

        std::vector<value_type> f{0, 1, 2, 3, 4, 5};
    };
}

